package com.linkoog.devtools.json.file_editer.editer.ui.jsonTreeTable;

import com.fasterxml.jackson.databind.node.TextNode;
import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
import com.intellij.ui.treeStructure.treetable.TreeTable;
import com.intellij.ui.treeStructure.treetable.TreeTableModel;
import com.intellij.ui.treeStructure.treetable.TreeTableTree;
import com.intellij.util.ui.ColumnInfo;
import com.linkoog.devtools.json.file_editer.editer.ui.JackJsonTreeNode;
import com.linkoog.devtools.json.file_editer.editer.ui.JackJsonTreeUtils;
import org.apache.commons.lang3.StringUtils;

import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import static java.lang.Math.max;

public class JsonStructureTreeTable extends TreeTable {

    TreeTableTree tree;
    JackJsonTreeNode rootNode;

    public JsonStructureTreeTable(){
        this(JackJsonTreeNode.DEFAULT);
    }

    private JsonStructureTreeTable(JackJsonTreeNode rootNode){
        super(new ListTreeTableModelOnColumns(rootNode, columns));
        this.rootNode = rootNode;
        init();
    }

    public void reset(String json){
        rootNode = JackJsonTreeUtils.buildJsonTree(json);

        ListTreeTableModelOnColumns listTreeTableModel = getTableModel();
        listTreeTableModel.setRoot(rootNode);
    }

    public ListTreeTableModelOnColumns getTableModel() {
        return (ListTreeTableModelOnColumns)super.getTableModel();
    }

    private void init(){
        tree = getTree();
        tree.setShowsRootHandles(true);
        tree.setRootVisible(false);
        setTreeCellRenderer(new TreeKeyCellRenderer());
        setAutoResizeMode(AUTO_RESIZE_LAST_COLUMN);

        int keyColumnWidth = max(125, getFontMetrics(getFont()).stringWidth(StringUtils.repeat("*", getMaxKeyColumnWidth(rootNode))));
        final TableColumn column0 = getColumnModel().getColumn(0);
        column0.setMaxWidth(400 + keyColumnWidth);
        column0.setPreferredWidth(keyColumnWidth);


        TableColumn tableColumn1 = getColumnModel().getColumn(1);
        tableColumn1.setCellRenderer(new TableValueRenderer());
    }

    private int getMaxKeyColumnWidth(TreeNode rootNode) {
        var length = 0;
        if (!rootNode.isLeaf()) {
            var maxChildLen = 0;
            for (int i = 0; i < rootNode.getChildCount(); i++) {
                maxChildLen = max(getMaxKeyColumnWidth(rootNode.getChildAt(i)), maxChildLen);
            }
            length += maxChildLen;
        }

        if (rootNode instanceof JackJsonTreeNode){
            JackJsonTreeNode node = (JackJsonTreeNode)rootNode;
            length += node.getName().length();
        }

        return length;
    }

    public TableCellEditor getCellEditor(int row, int column) {
        TreePath treePath = tree.getPathForRow(row);
        if (treePath == null){
            return super.getCellEditor(row, column);
        }

        JackJsonTreeNode node = (JackJsonTreeNode)treePath.getLastPathComponent();
        TableCellEditor editor = columns[column].getEditor(node);
        if (editor == null){
            return super.getCellEditor(row, column);
        }
        return editor;
    }

    private static final ColumnInfo<JackJsonTreeNode, String> KEY = new  ColumnInfo<>("Key") {
        public String valueOf(JackJsonTreeNode treeNode)  {
            return treeNode.getName();
        }

        public Class<TreeTableModel> getColumnClass() {
            return TreeTableModel.class;
        }

        public boolean isCellEditable(JackJsonTreeNode treeNode) {
            return false;
        }

        public TableCellRenderer getRenderer(JackJsonTreeNode treeNode) {
            return new TableKeyRenderer();
        }

        @Override
        public int getAdditionalWidth() {
            return 4;
        }
    };

    private static final ColumnInfo<JackJsonTreeNode, String> VALUE = new ColumnInfo<>("Value") {

        public String valueOf(JackJsonTreeNode treeNode) {
            return treeNode.getJson();
        }

        public boolean isCellEditable(JackJsonTreeNode treeNode) {
            return false;
        }

        public TableCellRenderer getRenderer(JackJsonTreeNode treeNode) {
            return new TableValueRenderer();
        }
    };

    private static final ColumnInfo[] columns = new ColumnInfo[]{KEY, VALUE};


}
